#!/bin/bash
sandboxdir=$(dirname $0)
. $sandboxdir/sb_vars.sh
. $sandboxdir/sb_common.sh

[ -z "$FRACTIONAL_TIME" ] && FRACTIONAL_TIME=''
[ -z "$MS_ACCURACY" ] && MS_ACCURACY=''
if [ -n "$FRACTIONAL_TIME" ]
then
    MS_ACCURACY=`echo $FRACTIONAL_TIME| perl -ne '$l=s/\d//g; print $l' `
    MS_ACCURACY="($MS_ACCURACY)"
    #echo "<$MS_ACCURACY>"
    #echo "<$FRACTIONAL_TIME>"
fi

SAMPLE_BLOB="%!+?/.,[]{}()*^&#@-_=abcdefghi0123456789"
SAMPLE_T=xyz
# SAMPLE_F=1.512345678901234
SAMPLE_F=1.012345678901234
SAMPLE_TINYINT=127
SAMPLE_U_TINYINT=255
SAMPLE_SMALLINT=32767
SAMPLE_U_SMALLINT=65535
SAMPLE_MEDIUMINT=8388607
SAMPLE_U_MEDIUMINT=16777215
SAMPLE_INT=2147483647
SAMPLE_U_INT=4294967295
SAMPLE_BIGINT=9223372036854775807
SAMPLE_U_BIGINT=18446744073709551615
SAMPLE_D=1969-09-01
MIN_D=1000-01-01
MAX_D=9999-12-31
SAMPLE_TIME=12:13:56$FRACTIONAL_TIME
MIN_TIME=00:00:00
MAX_TIME=23:59:59$FRACTIONAL_TIME
SAMPLE_DT="2003-04-26 09:15:57$FRACTIONAL_TIME"
MIN_DT="1000-01-01 00:00:00"
MAX_DT="9999-12-31 23:59:59$FRACTIONAL_TIME"
SAMPLE_ENUM="two"
SAMPLE_SET="red,blue"
SAMPLE_TS="2003-04-26 09:15:58$FRACTIONAL_TIME"

pass=0
fail=0
total_tests=0


TREPCTL=$TUNGSTEN_SB_NODE2/tungsten/tungsten-replicator/bin/trepctl

function make_my_cnf
{
    my_cnf=$1
    port=$2
    echo '[client]' > $my_cnf
    echo "user=$MYSQL_USER" >> $my_cnf
    echo "password=$MYSQL_PASSWORD" >> $my_cnf
    echo "port=$port" >> $my_cnf
    echo "host=127.0.0.1" >> $my_cnf
    if [ -n "$USE_SSL" ]
    then
        echo "$CLIENT_OPTIONS" >> $my_cnf
    fi
}

function write_to_master
{
    my_cnf=$1
    rmiport=$2
    dbport=$3
    service=$4
    topology=$5
    echo "# Topology $topology: writing to master <$service> rmiport:$rmiport dbport:$dbport - table test.t$rmiport "
    #cat $my_cnf
    #echo "."
    mysql --defaults-file=$my_cnf -e "drop table if exists test.t$rmiport"
    mysql --defaults-file=$my_cnf -e "create table test.t$rmiport(_id int not null primary key, c char(30), b blob, t text, ti time$MS_ACCURACY, d date, dt datetime$MS_ACCURACY, ts timestamp$MS_ACCURACY, f double(20,15), e enum ('one', 'two', 'three'), s set ('yellow','red', 'white','blue')) engine=innodb"
    if [ "$?" != "0" ] ; then exit ; fi
    mysql --defaults-file=$my_cnf -e "insert into test.t$rmiport values (1, 'inserted by node #$rmiport', '$SAMPLE_BLOB', '$SAMPLE_T', '$SAMPLE_TIME', '$SAMPLE_D', '$SAMPLE_DT', '$SAMPLE_TS', $SAMPLE_F,'$SAMPLE_ENUM', '$SAMPLE_SET')"
}

# Mongodb sample record
# { 
# "_id" : "1", 
# "c" : "inserted by node #10110", 
# "b" : "%!+?/.,[]{}()*^&#@-_=abcdefghi0123456789", 
# "t" : "xyz", 
# "ti" : "12:13:56", 
# "d" : "1969-09-01", 
# "dt" : "2003-04-26 11:15:57.0", 
# "ts" : "2003-04-26 09:15:58.0", 
# "f" : "1.012345678901234", 
# "e" : "two", 
# "s" : "red,blue" 
# }

function get_result_from_csv
{
    field=$1
    expected=$2
    delta=5
    field_no=`head -n 1 $CSV_FILE | perl -F'\|' -nale 'BEGIN{$field=shift};$n=0;for $f (@F) { $n++; print $n and exit if $f eq $field }' $field`
    value=`head -n 2 $CSV_FILE | tail -n 1 | perl -nle 'BEGIN{$wanted=shift; $n =0};while (/"([^"]+)"/g){print $1 if ++$n == $wanted}' $field_no`

    ok_equal "$value" "$expected" "*csv* field:$field "
}

function get_result
{
    my_cnf=$1
    rmiport=$2
    field=$3
    expected=$4
    # set -x
    if [ -n "$USE_FILEAPPLIER" ]
    then
        # echo "# test on field <$field> skipped - fileapplier"
        get_result_from_csv  $field "$expected"
        return
    fi
    DB_INFO=''
    if [ -n "$USE_MONGODB" ]
    then
        values=`(echo 'use test'; echo "db.t$rmiport.find()" ) | mongodb --quiet`
        export WANTED_FIELD=$field
        value=$(echo $values | perl -ne 'BEGIN{$f=$ENV{WANTED_FIELD}};print $1 if /"$f"\s+:\s+"([^"]+)"/')
        unset WANTED_FIELD
        DB_INFO='*mongo*'
    else
        value=$(mysql --defaults-file=$my_cnf -BN -e "select $field from test.t$rmiport ")
        unset DB_INFO
    fi
    ok_equal  "$value" "$expected" "$DB_INFO field:$field"
    # set +x
}

function read_from_slaves
{
    # set -x
    service=$1
    master_rmiport=$2
    topology=$3
    if [ "$topology" == "star" ]
    then
        SLAVES_LIST=$(multi_trepctl --role slave --fields service,rmiport --hide-headers --output list)
        echo "# Reading from all slaves (topology $topology)"
    else
        SLAVES_LIST=$(multi_trepctl --role slave,direct --fields service,rmiport --hide-headers --output list --service $service)
        echo "# Reading from slaves related to service $service"
    fi
    # echo "<$SLAVES_LIST>"
    for SERVICE_SLAVE in $(echo $SLAVES_LIST | tr ';' ' ')
    do
        sleep 1
        service=$(echo $SERVICE_SLAVE | tr ',' ' '| awk '{print $1}')
        rmiport=$(echo $SERVICE_SLAVE | tr ',' ' '| awk '{print $2}')
        db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.global.db.port | perl -nle 'print $1 if /"(\d+)"}?$/')
        if [ -z "$db_port" ]
        then
            db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.datasource.extractor.connectionSpec.port | perl -nle 'print $1 if /"(\d+)"}?$/')
        fi
        # echo "SSLAVE $SERVICE_SLAVE"
        # echo "service $service"
        # echo "rmiport $rmiport"
        # echo "db_port $db_port"
        # echo "MO_port $MONGODB_PORT"
        # echo "topology $topology"
        if [ "$topology" == "mongodb" -a  "$db_port" == "$MONGODB_PORT" ]
        then
            export USE_MONGODB=1 
        else
            unset USE_MONGODB
        fi
        if [ "$topology" == "fileapplier" -a  "$rmiport" == "$RMI_PORT_NODE3" ]
        then
            export USE_FILEAPPLIER=1 
            DELAY=$($TUNGSTEN_SB/${SB_PREFIX}3/trepctl properties -filter replicator.stage.q-to-dbms.blockCommitInterval | perl -lne 'print $1 if /"(\d+)s?"/')
            if [ -n "$DELAY" ]
            then
                if [ "$DELAY" != "0" ]
                then
                    # Making sure we are waiting enough.
                    DELAY=$(($DELAY+1))
                    echo "# Sleeping $DELAY seconds according to property 'replicator.stage.q-to-dbms.blockCommitInterval' in node 3"
                    sleep $DELAY
                fi
            fi
            CSV_DIR=$TUNGSTEN_SB/${SB_PREFIX}3/tungsten/tungsten-replicator/data/$service/test
            CSV_FILE=$( ls -otr $CSV_DIR/t$master_rmiport*.csv | awk '{print $NF}' | tail -n 1 )
            # echo "### <$CSV_FILE>"
        else
            unset USE_FILEAPPLIER
            unset CSV_FILE
        fi

        #echo "slave service $service"
        echo "# slave <$service> rmiport:$rmiport - dbport: $db_port"
        MY_CNF=/tmp/myslave_$service.cnf
        make_my_cnf $MY_CNF $db_port
        #mysql --defaults-file=$MY_CNF -e 'select "slave", @@hostname, @@server_id, @@port'
        if [ -n "$USE_MONGODB" -o -n "$USE_FILEAPPLIER" ]
        then
            numrecs=1
        else
            numrecs=$(mysql --defaults-file=$MY_CNF -BN -e "select count(*) from test.t$master_rmiport ")
        fi
        ok_equal $numrecs 1 "record count"
        get_result $MY_CNF $master_rmiport c  "inserted by node #$master_rmiport"
        get_result $MY_CNF $master_rmiport b  "$SAMPLE_BLOB"
        get_result $MY_CNF $master_rmiport t  "$SAMPLE_T"
        get_result $MY_CNF $master_rmiport ti "$SAMPLE_TIME"
        get_result $MY_CNF $master_rmiport d  "$SAMPLE_D"
        #if [ "$topology" != "mongodb" ]
        #then
            get_result $MY_CNF $master_rmiport dt "$SAMPLE_DT"
        #fi
        get_result $MY_CNF $master_rmiport ts "$SAMPLE_TS"
        get_result $MY_CNF $master_rmiport f  "$SAMPLE_F"
        get_result $MY_CNF $master_rmiport e  "$SAMPLE_ENUM"
        get_result $MY_CNF $master_rmiport s  "$SAMPLE_SET"
        rm -f $MY_CNF
    done
}

TOPOLOGY=$(cat $TUNGSTEN_SB/topology)

if [ "$TOPOLOGY" == "direct" ]
then
    multi_trepctl_node2=$TUNGSTEN_SB/${SB_PREFIX}2/tungsten/tungsten-replicator/scripts/multi_trepctl    
    MASTER_LIST=$($multi_trepctl_node2 --fields service,rmiport,role --hide-headers --output list --paths=$TUNGSTEN_SB/${SB_PREFIX}2)
else
    MASTER_LIST=$(multi_trepctl --role master --fields service,rmiport,role --hide-headers --output list)
fi
# MASTER_LIST=$(multi_trepctl --fields service,pipelineSource,rmiport,role --hide-headers --output list)
echo '' > /tmp/used_ports
for SERVICE_MASTER in $(echo $MASTER_LIST | tr ';' ' ')
do
    service=$(echo $SERVICE_MASTER | tr ',' ' '| awk '{print $1}')
    #pipeline=$(echo $SERVICE_MASTER | tr ',' ' '| awk '{print $2}')
    rmiport=$(echo $SERVICE_MASTER | tr ',' ' '| awk '{print $2}')
    role=$(echo $SERVICE_MASTER | tr ',' ' '| awk '{print $3}')
    # db_port=$(echo $pipeline | perl -nle 'print $1 if m{^jdbc:\w+:[^:]+://[^:]+:(\d+)}')

    extractor_db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.global.extract.db.port | perl -nle 'print $1 if /"(\d+)"}?$/')
    if [ -z "$extractor_db_port" ]
    then
        echo "error retrieving the extractor port"
        exit 1
    fi
    applier_db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.applier.dbms.port | perl -nle 'print $1 if /"(\d+)"}?$/')
    if [ -z "$applier_db_port" ]
    then
        applier_db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.datasource.global.connectionSpec.port | perl -nle 'print $1 if /"(\d+)"}?$/')
    fi
    if [ -z "$applier_db_port" ]
    then
        echo "error retrieving the applier port"
        exit 1
    fi
    db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.global.db.port | perl -nle 'print $1 if /"(\d+)"}?$/')
    if [ -z "$db_port" ]
    then
        db_port=$($TREPCTL -port $rmiport -service $service properties -filter replicator.datasource.global.connectionSpec.port | perl -nle 'print $1 if /"(\d+)"}?$/')
    fi
    if [ -z "$db_port" ]
    then
        echo "error retrieving the global db port"
        exit 1
    fi
    if [ "$extractor_db_port" != "$applier_db_port" ]
    then
        db_port=$extractor_db_port
    fi
    if [ -n "$TEST_EXIT_CODE" ]
    then
        echo "Testing exit code <$TEST_EXIT_CODE>"
        exit $TEST_EXIT_CODE
    fi
    if [ -n "$TEST_FAILURE_NUM" ]
    then
        echo "ok - fake pass for testing"
        echo "not ok - fake failure for testing"
        echo "ok - another fake pass for testing"
        echo "not ok - more fake failure for testing"
        exit 0
    fi
    #echo "master service $service"
    #echo "master rmiport $rmiport"
    #echo "master db port $db_port"
    if [ -n "$db_port" ]
    then
        # echo '#--------------------'
        # cat /tmp/used_ports
        # echo '#--------------------'
        used_port=$(grep -w $db_port /tmp/used_ports)
        if [ -z "$used_port" ]
        then
            echo $db_port >> /tmp/used_ports
            MY_CNF=/tmp/mymaster_$service.cnf
            make_my_cnf $MY_CNF $db_port
            #mysql --defaults-file=$MY_CNF -e 'select "master", @@hostname, @@server_id, @@port'
            if [ "$role" != "master" ]
            then
                rmiport="NO_RMI_PORT"
            fi
            write_to_master $MY_CNF $rmiport $db_port $service $TOPOLOGY
            rm -f $MY_CNF
            # echo ""
            read_from_slaves $service $rmiport $TOPOLOGY
        fi
    fi
done
rm -f /tmp/used_ports 

echo "# total tests: $total_tests"
echo "# passed     : $pass"
echo "# failed     : $fail"

if [ "$fail" != "0" ]
then
    exit 1
fi

